package io.mft.as.ar.gateway.client;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import io.mft.as.ar.gateway.constants.GatewayConstants;
import io.mft.as.ar.gateway.pool.BusPool;
import io.mft.as.ar.gateway.util.HttpUtil;

/**
 * 描述: 网关服务信息
 * 版权: Copyright (c) 2012 
 * 公司: 思迪科技 
 * 作者: 李建 
 * 版本: 1.0 
 * 创建日期: 2012-3-22 
 * 创建时间: 下午4:24:14
 */
public class Server
{


	/**
	 * 序列号，用于多个网关时负载计算
	 */
	private AtomicLong invokeCount = new AtomicLong(0);

	private String gateWayName = "";

	private String version = "2";

	private int poolSize = 50;

	private int LBMode = 1;

	private int scanInterval = 10000;

	private long scanAliveInterval = 10000;

	private long checkPoolExpired = 60000;

	private String scanServerType = "";

	private String httpScanAddr = "";                            //http服务器监控地址

	private String httpRequestAddr = "";                            //http服务器请求地址

	private int recvTimeout = 0;                             //连接超时时间，默认10秒

	private String key = "";

	private NetAddress[] netAddressArr = null;

	private List<BusPool> asPoolArr = null;

	private int mode = 0;

	public Server(String name, Map<String, String> configMap)
	{
		this.gateWayName = name;
		if(configMap != null)
		{
			version = MapUtil.getStr(configMap, GatewayConstants.BUS_CONFIG_FIELD_VERSION);
			poolSize = MapUtil.getInt(configMap, GatewayConstants.BUS_CONFIG_FIELD_POOLSIZE);
			LBMode = MapUtil.getInt(configMap, GatewayConstants.BUS_CONFIG_FIELD_LBMODE);
			scanInterval = MapUtil.getInt(configMap, GatewayConstants.BUS_CONFIG_FIELD_SCANINTERVAL);
			//scanAliveInterval = MapUtil.getLong(configMap, GatewayConstants.BUS_CONFIG_FIELD_SCANALIVEINTERVAL);
			//checkPoolExpired = MapUtil.getLong(configMap, GatewayConstants.BUS_CONFIG_FIELD_CHECKPOOLEXPIRED);
			//scanServerType = MapUtil.getStr(configMap, GatewayConstants.BUS_CONFIG_FIELD_SCANSERVERTYPE);
			//httpScanAddr = MapUtil.getStr(configMap, GatewayConstants.BUS_CONFIG_FIELD_HTTPSCANADDR);
			//httpRequestAddr = MapUtil.getStr(configMap, GatewayConstants.BUS_CONFIG_FIELD_HTTPREQUESTADDR);
			if(ObjectUtil.isEmpty(scanServerType))
			{
				//默认是socket类型
				scanServerType = GatewayConstants.SCAN_SERVERTYPE_SOCKET;
			}
			mode = MapUtil.getInt(configMap, GatewayConstants.BUS_CONFIG_FIELD_MODE);
			recvTimeout = MapUtil.getInt(configMap, GatewayConstants.BUS_CONFIG_FIELD_RECVTIMEOUT);
			key = MapUtil.getStr(configMap, GatewayConstants.BUS_CONFIG_FIELD_KEY);

			poolSize = (poolSize <= 0) ? 50 : poolSize;

			//缺省闲置最大时间，默认为5分钟
			scanAliveInterval = (scanAliveInterval <= 0) ? 300000 : scanAliveInterval;

			//缺省间隔检查时间，默认为1分钟
			checkPoolExpired = (checkPoolExpired <= 0) ? 60000 : checkPoolExpired;

			String serverList = MapUtil.getStr(configMap, GatewayConstants.BUS_CONFIG_FIELD_GATEWAY);

			setNetAddressArr(scanServerType, serverList, httpScanAddr, httpRequestAddr);

		}
	}

	public int getScanInterval()
	{
		return scanInterval;
	}

	public long getScanAliveInterval()
	{
		return scanAliveInterval;
	}

	public long getCheckPoolExpired()
	{
		return checkPoolExpired;
	}

	protected String getScanServerType()
	{
		return scanServerType;
	}

	protected String getHttpScanAddr()
	{
		return httpScanAddr;
	}

	public String getHttpRequestAddr()
	{
		return httpRequestAddr;
	}

	public String getGateWayName()
	{
		return gateWayName;
	}

	public NetAddress[] getNetAddressArr()
	{
		return netAddressArr;
	}

	/**
	 *
	 * @描述: 设置服务器信息
	 * @作者: liwei
	 * @创建日期: 2016年11月17日 下午8:23:47
	 * @param serverType 服务器通讯协议类型  socket/http/https
	 * @param serverList 服务器IP和端口信息，多个用|分隔
	 * @param httpScanAddr web服务器扫描地址
	 * @param httpRequestAddr web服务器接口请求地址
	 */
	public void setNetAddressArr(String serverType, String serverList, String httpScanAddr, String httpRequestAddr)
	{
		if(ObjectUtil.isNotEmpty(serverList.trim()))
		{
			String[] gateArry = serverList.split("\\|");
			int port = 0;
			if(gateArry != null && gateArry.length > 0)
			{
				netAddressArr = new NetAddress[gateArry.length];

				for(int i = 0; i < gateArry.length; i++)
				{
					String[] ipPortArry = gateArry[i].split(":");
					String ipStr = ipPortArry[0];
					if(ipPortArry.length > 1)
					{
						port = Integer.parseInt(ipPortArry[1]);
					}
					if(ObjectUtil.isNotEmpty(ipStr) && port > 0)
					{
						NetAddress netAddress;
						if(GatewayConstants.SCAN_SERVERTYPE_SOCKET.equals(serverType))
						{
							netAddress = new NetAddress();
							netAddress.setIP(ipStr);
							netAddress.setPort(port);
						}
						else
						{
							netAddress = new NetAddress(serverType, ipStr, port, httpScanAddr, httpRequestAddr);
						}

						netAddress.setAlive(false);
						netAddressArr[i] = netAddress;
					}
				}
			}
		}
		else
		{
			netAddressArr = null;
		}
	}

	public int getPoolSize()
	{
		return poolSize;
	}

	public int getMode()
	{
		return mode;
	}

	public int getLBMode()
	{
		return LBMode;
	}

	public String getVersion()
	{
		return version;
	}

	public int getRecvTimeout()
	{
		return recvTimeout;
	}

	public String getKey()
	{
		return key;
	}

	/**
	 * 描述：获取网关服务
	 * 作者：李建
	 * 时间：2013-1-21 下午4:34:43
	 * @return
	 */
	public NetAddress getRmdServer() throws Exception
	{
		ArrayList<NetAddress> tempList = new ArrayList<NetAddress>();
		if(netAddressArr != null)
		{
			for(NetAddress netAddress : netAddressArr)
			{
				if(netAddress.isAlive())
				{
					tempList.add(netAddress);
				}
			}
		}

		if(tempList.isEmpty())
		{
			/**
			 * 遍历BUS服务器信息，检查是否存活
			 * 解决调试问题
			 */
			boolean isFlag = false;
			if(netAddressArr != null)
			{
				for(int i = 0; i < netAddressArr.length; i++)
				{
					NetAddress netAddress = (NetAddress) netAddressArr[i];
					boolean isAlive = HttpUtil.connectServer(netAddress);
					if(isAlive)
					{
						isFlag = true;
						netAddress.setAlive(true);
						tempList.add(netAddress);
					}
				}
			}
			if(!isFlag)
			{
				throw new Exception("没有取到存活的" + this.gateWayName + "网关列表,请查看服务器是否连接正常！");
			}
		}

		if(tempList.size() == 1)
		{
			return tempList.get(0);
		}
		else
		{
			int i;
			if(this.getLBMode() == GatewayConstants.LBMODE_RANDOM)
			{
				//随机模式
				Random random = new Random();
				i = random.nextInt(tempList.size());
			}
			else if(this.getLBMode() == GatewayConstants.LBMODE_BACKUPS)
			{
				//主备模式，只取第一台BUS服务器
				i = 0;
			}
			else
			{
				//顺序模式
				i = (int) (invokeCount.incrementAndGet() % tempList.size());

			}
			return tempList.get(i);
		}
	}

	/**
	 *
	 * 描述：
	 * 作者：李炜
	 * 时间：Dec 4, 2013 12:54:19 PM
	 * @return
	 */
	public BusPool getRmdASPool() throws Exception
	{

		ArrayList<BusPool> tempList = new ArrayList<BusPool>();
		if(asPoolArr != null)
		{
			for(BusPool asPool : asPoolArr)
			{
				if(asPool.isUseable())
				{
					tempList.add(asPool);
				}
			}
		}
		if(tempList.isEmpty())
		{
			throw new Exception("没有取到存活的" + this.gateWayName + "网关列表,请查看服务器是否连接正常！");
		}

		if(tempList.size() == 1)
		{
			return tempList.get(0);
		}
		else
		{
			int i;
			if(this.getLBMode() == GatewayConstants.LBMODE_RANDOM)
			{
				//随机模式
				Random random = new Random();
				i = random.nextInt(tempList.size());
			}
			else if(this.getLBMode() == GatewayConstants.LBMODE_BACKUPS)
			{
				//主备模式，只取第一台BUS服务器
				i = 0;
			}
			else
			{
				//顺序模式
				i = (int) (invokeCount.incrementAndGet() % tempList.size());

			}
			return tempList.get(i);
		}
	}

	public List<BusPool> getAsPoolArr()
	{
		return asPoolArr;
	}

	public void setAsPoolArr(BusPool busPool)
	{
		if(this.asPoolArr != null)
		{
			this.asPoolArr.add(busPool);
		}
	}

	public void setAsPoolArr(List<BusPool> asPoolArr)
	{
		this.asPoolArr = asPoolArr;
	}

	public void removeAsPool(BusPool busPool)
	{
		if(this.asPoolArr != null && busPool != null)
		{
			this.asPoolArr.remove(busPool);
		}
	}
}
